﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using SharepointListFieldsMassiveCreator.SPSReference;

namespace SharepointListFieldsMassiveCreator
{
    public partial class MainForm : Form
    {
        private List<FieldsDTO> fieldsList;

        public MainForm()
        {
            InitializeComponent();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            if (textBoxXml.Visible)
                HideXmlBox();

            DialogResult r = this.ofdSelectListDefinitionFile.ShowDialog();

            if (r == DialogResult.OK || r == DialogResult.Yes)
            {
                this.txtSourceFile.Text = ofdSelectListDefinitionFile.FileName;
            }
        }

        private void btnRead_Click(object sender, EventArgs e)
        {
            if (IsSourceFileEmpty())
                return;

            if (textBoxXml.Visible)
                HideXmlBox();

            fieldsList = null;
            fieldsList = new List<FieldsDTO>();

            String[] fields = System.IO.File.ReadAllLines(this.txtSourceFile.Text);

            foreach (string field in fields)
            {
                string fieldTrimed = field.Trim();

                // Skip comments and empty lines
                if ((fieldTrimed.Length == 0) || (fieldTrimed.StartsWith("//")))
                    continue;

                if (fieldTrimed.Contains(','))
                {
                    if (fieldTrimed.Contains('|'))
                        this.fieldsList.Add(this.BuildFieldDTOItemByStringWithCommaAndPipe(fieldTrimed));
                    else
                        this.fieldsList.Add(this.BuildFieldDTOItemByStringWithComma(fieldTrimed));
                }
                else
                {
                    this.fieldsList.Add(this.BuildFieldDTOItem(fieldTrimed, "Text"));
                }
            }
            this.dgvIdentifiedFieldsList.DataSource = fieldsList;
        }

        private FieldsDTO BuildFieldDTOItemByStringWithCommaAndPipe(string field)
        {

            return new FieldsDTO() { FieldName = field.Split(',')[0].Trim(), FieldType = field.Split(',')[1].Split('|')[0].Trim(), FieldDefinition = field.Split(',')[1].Split('|')[1].Trim() };
        }

        private FieldsDTO BuildFieldDTOItemByStringWithComma(String field)
        {
            return new FieldsDTO() { FieldName = field.Split(',')[0].Trim(), FieldType = field.Split(',')[1].Trim(), FieldDefinition = "<Field><Type>" + field.Split(',')[1].Trim() + "</Type></Field>" };
        }

        private FieldsDTO BuildFieldDTOItem(String fieldName, String fieldType)
        {
            return new FieldsDTO() { FieldName = fieldName, FieldType = fieldType, FieldDefinition = "<Field><Type MaxLength=\"50\">Text</Type></Field>" };
        }

        public class FieldsDTO
        {
            public String FieldName { get; set; }
            public String FieldType { get; set; }
            public String FieldDefinition { get; set; }
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnGenerateGUID_Click(object sender, EventArgs e)
        {
            if (textBoxXml.Visible)
                HideXmlBox();

            this.txtGUID.Text = System.Guid.NewGuid().ToString().Replace("{", "").Replace("}", "");
        }

        private void btnBuildList_Click(object sender, EventArgs e)
        {
            if (IsListNameEmpty())
                return;

            if (IsGuidEmpty())
                return;

            if (textBoxXml.Visible)
                HideXmlBox();

            String serviceUrl = String.Empty;

            try
            {
                //Web service call for create the list.
                SPSReference.Lists service;
                using (service = new Lists())
                {
                    serviceUrl = System.Configuration.ConfigurationManager.AppSettings["serviceUrl"];
                    service.Url = serviceUrl;
                    service.UseDefaultCredentials = false;
                    service.Timeout = System.Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["serviceTimeout"]);
                    NetworkCredential credential = new NetworkCredential(
                        System.Configuration.ConfigurationManager.AppSettings["serviceUserName"],
                        System.Configuration.ConfigurationManager.AppSettings["servicePassword"],
                        System.Configuration.ConfigurationManager.AppSettings["serviceDomain"]);
                    service.Credentials = credential;
                    var nodo = service.AddList(this.txtListName.Text,
                                    "List automatically generated with a tool from a definition file.", 100);
                    this.SaveLogAndNotifyUser(nodo, "ListCreation");
                }
            }
            catch (Exception ex)
            {
                String userMessage =
                    "Error Message:\n"
                    + ex.Message
                    + "\n\nList Name: '"
                    + this.txtListName.Text
                    + "' already exists in site: \n"
                    + serviceUrl;
                System.Windows.Forms.MessageBox.Show(userMessage);
            }
        }

        private void btnProcess_Click(object sender, EventArgs e)
        {
            if (IsListNameEmpty())
                return;

            if (IsGuidEmpty())
                return;

            if (textBoxXml.Visible)
                HideXmlBox();

            String xmlForUpdateList = String.Empty;

            try
            {
                //Web service call for update the list definition.
                SPSReference.Lists service;
                using (service = new Lists())
                {
                    service.Url = System.Configuration.ConfigurationManager.AppSettings["serviceUrl"];
                    service.UseDefaultCredentials = false;
                    service.Timeout = System.Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["serviceTimeout"]);
                    NetworkCredential credential = new NetworkCredential(
                        System.Configuration.ConfigurationManager.AppSettings["serviceUserName"],
                        System.Configuration.ConfigurationManager.AppSettings["servicePassword"],
                        System.Configuration.ConfigurationManager.AppSettings["serviceDomain"]);
                    service.Credentials = credential;

                    //Xml objects required for the update operation.
                    XmlNode ndList = service.GetList(this.txtListName.Text);
                    this.txtGUID.Text = ndList.SelectSingleNode("/").Attributes["ID"].Value.Replace("{", "").Replace("}", "");
                    XmlNode ndVersion = ndList.Attributes["Version"];

                    XmlDocument xmlDoc = new System.Xml.XmlDocument();

                    XmlNode ndAddedFields = xmlDoc.CreateNode(XmlNodeType.Element, "Fields", "");
                    ndAddedFields.InnerXml = GetXmlForUpdateList();
                    xmlForUpdateList = ndAddedFields.OuterXml;
                    var nodo = service.UpdateList(this.txtGUID.Text, null, ndAddedFields, null, null, ndVersion.Value);
                    this.SaveLogAndNotifyUser(nodo, "ListUpdate");
                }
            }
            catch (Exception ex)
            {
                String userMessage =
                    "Error Message:\n"
                    + ex.Message
                    + "\n\nStack Trace:\n"
                    + ex.StackTrace
                    + "\n\nXmlForUpdateList:\n"
                    + xmlForUpdateList;
                System.Windows.Forms.MessageBox.Show(userMessage);
                textBoxXml.Text = xmlForUpdateList;
                ShowXmlBox();
            }
        }

        private void ShowXmlBox()
        {
            if (textBoxXml.Text != String.Empty)
            {
                textBoxXml.Visible = true;
                Form form = MainForm.ActiveForm;
                form.SetBounds(form.Location.X, form.Location.Y, form.Size.Width, 800);
            }
        }

        private void HideXmlBox()
        {
            textBoxXml.Text = String.Empty;
            textBoxXml.Visible = false;
            Form form = MainForm.ActiveForm;
            form.SetBounds(form.Location.X, form.Location.Y, form.Size.Width, 600);
        }

        private bool IsListNameEmpty()
        {
            bool isEmpty = false;
            if (this.txtListName.Text == String.Empty)
            {
                String userMessage = "The List Name is empty. \n\nPlease provide a List Name for creating a list.";
                System.Windows.Forms.MessageBox.Show(userMessage);
                isEmpty = true;
            }

            return isEmpty;
        }

        private bool IsGuidEmpty()
        {
            bool isEmpty = false;
            if (this.txtGUID.Text == String.Empty)
            {
                String userMessage = "The Guid is empty. \n\nPlease generate a Guid.";
                System.Windows.Forms.MessageBox.Show(userMessage);
                isEmpty = true;
            }

            return isEmpty;
        }

        private bool IsSourceFileEmpty()
        {
            bool isEmpty = false;
            if (this.txtSourceFile.Text == String.Empty)
            {
                String userMessage = "Source File is empty. \n\nPlease type in the name of a text file  or browse to a source file.";
                System.Windows.Forms.MessageBox.Show(userMessage);
                isEmpty = true;
            }

            return isEmpty;
        }

        private void SaveLogAndNotifyUser(XmlNode nodo, String operationType)
        {
            String userMessage = "";
            if (operationType == "ListUpdate")
                userMessage =
                    "Your changes were applied successfully, an operation result log was generated and stored at the following location:\n\r";
            else
                userMessage =
                    "Your new list was generated successfully, an operation result log was generated and stored at the following location:\n\r";

            if (operationType != "ListUpdate")
            {
                String listID = nodo.SelectSingleNode("/").Attributes["ID"].Value.ToString();
                this.txtGUID.Text = listID.Replace("{", "").Replace("}", "");
            }
            String strRutaLog = Application.StartupPath + "\\" + operationType + "_" +
                                DateTime.Now.ToString("yyyyMMddHHmmss") + "_" + this.txtGUID.Text + ".log";
            System.IO.File.WriteAllText(strRutaLog, nodo.OuterXml);

            userMessage += "\n\n" + strRutaLog;
            System.Windows.Forms.MessageBox.Show(userMessage);
        }

        private String GetXmlForUpdateList()
        {
            StringBuilder sb = new StringBuilder();

            for (int i = 0; i < this.dgvIdentifiedFieldsList.Rows.Count; i++)
            {
                sb.Append(String.Format(SharepointListFieldsMassiveCreator.Properties.Resources.UpdateListMethodWraper,
                    FieldSchemaGenerationHelper.GetFieldDefinition(this.dgvIdentifiedFieldsList.Rows[i].Cells[0].Value.ToString(), this.dgvIdentifiedFieldsList.Rows[i].Cells[2].Value.ToString()), (i + 1).ToString()));
            }
            return sb.ToString();
        }
    }
}
